#include "message.h"
#include "book.h"


bool_t xdr_char_tab (XDR * xdr, char* str, int size)
{
        bool_t b = TRUE;
        int i;
        
        // Encodage
        if (xdr->x_op == XDR_ENCODE || xdr->x_op == XDR_DECODE)
        {
                for (i=0; i<size; i++)
                {
                        b = b && xdr_char(xdr, &(str[i]));
                }               
        }
        
        return b;
}

bool_t xdr_message (XDR * xdr, Message * msg)
{
        bool_t b;
        int i;
        
        // Décodage et encodage
        if (xdr->x_op == XDR_ENCODE || xdr->x_op == XDR_DECODE)
        {
                b = xdr_int(xdr, &(msg->timestamp)) &&
                    xdr_int(xdr, &(msg->type)) && 
                    xdr_char_tab(xdr, msg->ipSender,SIZEIP) && 
                    xdr_char_tab(xdr, msg->ipReceiver,SIZEIP) && 
                    xdr_char_tab(xdr, msg->nameSender,SIZENAME) &&      
                    xdr_char_tab(xdr, msg->nameReceiver,SIZENAME) && 
                    xdr_int(xdr, &(msg->size));
                    
                if (b == FALSE)
                {
                        return FALSE;
                }
                
                // Allocation dynamique du message lors du décodage
                if (xdr->x_op == XDR_DECODE)
                {
                        msg->message = (char*) malloc(msg->size * sizeof(char));
                }
                
                for (i=0; i<msg->size; i++)
                {
                        b = b && xdr_char(xdr, &((msg->message)[i]));
                }
        }
        
        return b;
}

bool_t isAlreadyReceived (Message * msg)
{
        bool_t b = FALSE;
        int i;
        int taille = msgReceived.nbMessageReceived;

        for(i=0;i<taille;i++)
        {
                if(((msgReceived.list)[i].timestamp == msg->timestamp) && (strcmp((msgReceived.list)[i].ipSender,msg->ipSender) == 0))
                {
                        b = TRUE;                       // the message is already received
                        i = taille;                     // to end the loop
                }
        }

        return b;
}


void addMsgReceived (Message msg)               // add the message in MessageReceived
{
        int taille = msgReceived.nbMessageReceived + 1;         // new size
        //TODO plante
        printf("taille == %d\n", taille);
        (msgReceived.list) = realloc((msgReceived.list), taille* sizeof(MessageReceived));
        printf("ok\n");

        MessageReceived mr;
        mr.timestamp = msg.timestamp;
        strcpy(mr.ipSender, msg.ipSender);

        (msgReceived.list)[taille] = mr;
        (msgReceived.nbMessageReceived)++;
}

void send_message_all(char * message, int type)
{
        int i, time_s;
        
        /* Sending "CONNECT" to all contacts */
        Message * msg = malloc(adressBook.nbContacts * sizeof(Message));
        
        /* Timestamp */
        struct timeval tv;
        gettimeofday(&tv,NULL);
        time_s = tv.tv_sec;
        
        /* For each contact ... */
        for (i=0; i<adressBook.nbContacts; i++)
        {
                ATTENTE
        
                Contact c = adressBook.contacts[i];
                
                msg[i].timestamp = time_s;
                msg[i].type = type;
                strcpy(msg[i].ipSender, adressBook.me.ip);
                strcpy(msg[i].nameSender, adressBook.me.name);          
                
                msg[i].size = strlen(message)+1;
                msg[i].message = malloc(RAWSIZE * sizeof(char));
                memset(msg[i].message, '\0', RAWSIZE);
                strcpy(msg[i].message, message);
                
                if(type == CONNECTION || c.connected)
                {
                        // Contact name
                        strcpy(msg[i].nameReceiver, c.name);
                
                        // Contact ip
                        strcpy(msg[i].ipReceiver, c.ip);
                
                        send_message(msg[i]); 
                }
        }
        
        sleep(1);
        
}

int send_message(Message msg)
{       
        printf("send msg atteint\n");
        pthread_t id;
        printMessage(msg,"aa");
        pthread_create (&id, NULL, send_message_thread,(void *)&msg);
        
        return 0;
}

void printMessage(Message msg, char * truc)
{
        printf("%sMessage :\n",truc);
        printf("\t %stimestamp : %d\n",truc,msg.timestamp);
        printf("\t %stype : %d\n",truc,msg.type);
        printf("\t %sipSender : %s\n",truc,msg.ipSender);
        printf("\t %sipReceiver : %s\n",truc,msg.ipReceiver);
        printf("\t %snameSender : %s\n",truc,msg.nameSender);
        printf("\t %snameReceiver : %s\n",truc,msg.nameReceiver);
        printf("\t %ssize : %d\n",truc,msg.size);
        printf("\t %smessage : %s\n",truc,msg.message);
}

void* send_message_thread(void* arg)
{
        printf("thread atteint\n");
        Message* msg = (Message*) arg;

        Message msg_cpy;
        memcpy((void*)&msg_cpy,(void*)msg,sizeof(*msg));
        //printMessage(*msg,"aa");
        //printMessage(msg_cpy,"bb");
        
        enum clnt_stat stats;
        
        int result;
        
        stats = callrpc(msg_cpy.ipReceiver,                            // Contact IP
                       PROGNUM, VERSNUM, PROCNUM,              // Procedure
                       (xdrproc_t) xdr_message, (char *) &msg_cpy,  // out: Message
                       (xdrproc_t) xdr_int, (char *) &result); // in : int
                
        if (stats != RPC_SUCCESS && msg->type==STANDARD)
        {
                printf("Le message \"%s\" n'a pu être remis à %s\n",msg_cpy.message,msg_cpy.nameReceiver);
        }
        
        if (result == METOO)
        {
                connectionContact(msg_cpy.nameReceiver);
                printf("* %s est connecté(e)\n", msg_cpy.nameReceiver);
        }
        
        return NULL;
}

void send_message_contact(char* name, char* message)
{
        int i;

        // Nom de contact ?
        for (i=0; i<adressBook.nbContacts; i++)
        {
                ATTENTE
                
                // Si le nom de contact correspond
                if (strcmp(name, adressBook.contacts[i].name) == 0)
                {
                        // Formulation du message
                        Message msg;
                        
                        struct timeval tv;
                        gettimeofday(&tv,NULL);
                        msg.timestamp = tv.tv_sec;
                        /* Message type */
                        msg.type = STANDARD;
                        /* Sender IP */
                        strcpy(msg.ipSender, adressBook.me.ip);
                        /* Sender name */
                        strcpy(msg.nameSender, adressBook.me.name);
                        
                        /* Message contents */
                        msg.size = strlen(message)+1;
                        msg.message = malloc(sizeof(char) * RAWSIZE);
                        memset(msg.message, '\0', RAWSIZE);
                        strcpy(msg.message, message);
                        
                        // On lui envoie un message
                        Contact c = adressBook.contacts[i];
                
                        if(c.connected)
                        {
                                // Contact name
                                strcpy(msg.nameReceiver, c.name);
                
                                // Contact ip
                                strcpy(msg.ipReceiver, c.ip);

                                send_message(msg);
                        }
                        
                        return;
                }
                
        }
}

